package org.xmppbot;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;

import org.xmpp.packet.JID;
import org.xmppbot.session.IncomingServerSession;
import org.xmppbot.session.LocalSession;
import org.xmppbot.util.cache.CacheFactory;
import org.xmppbot.util.cache.Cache;

/**
 * Управляет входящими и исходящими соединениями
 * @author stas
 *
 */
public class SessionManager {
    /**
     * Cache (unlimited, never expire) that holds list of incoming sessions
     * originated from the same remote server (domain/subdomain). For instance, jabber.org
     * may have 2 connections to the server running in jivesoftware.com (one socket to
     * jivesoftware.com and the other socket to conference.jivesoftware.com).
     * Key: remote hostname (domain/subdomain), Value: list of stream IDs that identify each socket.
     */
    private Cache<String, ArrayList<String>> hostnameSessionsCache;

    /**
     * Map that holds sessions that has been created but haven't been authenticated yet. The Map
     * will hold client sessions.
     */
    private Map<String, LocalSession> preAuthenticatedSessions = new ConcurrentHashMap<String, LocalSession>();
    
    public void initialize(){
    	hostnameSessionsCache = CacheFactory.createCache("Sessions by Hostname");
    }
    
    public boolean isMultipleServerConnectionsAllowed() {
    	// Т.к. мы не используем пока БД для хранения настроек
    	return true;
    }
    
    /**
     * Returns the list of sessions that were originated by a remote server. The list will be
     * ordered chronologically.  IncomingServerSession can only receive packets from the remote
     * server but are not capable of sending packets to the remote server.
     *
     * @param hostname the name of the remote server.
     * @return the sessions that were originated by a remote server.
     */
    public List<IncomingServerSession> getIncomingServerSessions(String hostname) {

    	// TODO У нас есть только интерфейсы Session, LocalSession и RemoteSession. IncomingServerSession надо поменять на LocalSession
         
    	List<String> streamIDs;
        // Get list of sockets/sessions coming from the remote hostname
        Lock lock = CacheFactory.getLock(hostname, hostnameSessionsCache);
        try {
        	lock.lock();
            streamIDs = hostnameSessionsCache.get(hostname);
        }finally {
            lock.unlock();
        }

        if (streamIDs == null) {
            return Collections.emptyList();
        }else {
            List<IncomingServerSession> sessions = new ArrayList<IncomingServerSession>();
            for (String streamID : streamIDs) {
//            	IncomingServerSession session
            
            }        
        }
        return null;
    }

    /**
     * Returns the session responsible for this JID data. The returned Session may have never sent
     * an available presence (thus not have a route) or could be a Session that hasn't
     * authenticated yet (i.e. preAuthenticatedSessions).
     *
     * @param from the sender of the packet.
     * @return the <code>Session</code> associated with the JID.
     */
    public LocalSession getSession(JID from){
        // Return null if the JID is null or belongs to a foreign server. If the server is
        // shutting down then serverName will be null so answer null too in this case.
        if (from == null || BotManager.BOT_SERVER_DOMAIN == null || !BotManager.BOT_SERVER_DOMAIN.equals(from.getDomain())) {
            return null;
        }

        // Initially Check preAuthenticated Sessions
//        if (from.getResource() != null) {
//            ClientSession session = localSessionManager.getPreAuthenticatedSessions().get(from.getResource());
//            if (session != null) {
//                return session;
//            }
//        }

        if (from.getResource() == null || from.getNode() == null) {
            return null;
        }

        return null;
    }
}
